#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "sk_root_item.h"
#include "sk_game_model.h"
#include "sk_game_project.h"

#include <QInputDialog>
#include <QFileDialog>
#include <QMessageBox>
#include <QDockWidget>
#include <QDebug>
#include <QSettings>
#include <QAbstractItemDelegate>
#include <QVariant>

#include "simulationwindow.h"
#include "projectexplorer.h"
#include "leveleditor.h"
#include "userdata.h"

class TreeDelegate : public QAbstractItemDelegate
{
public:
    TreeDelegate(QObject * parent);
    void paint (QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

TreeDelegate::TreeDelegate(QObject * parent)
    :
QAbstractItemDelegate(parent)
{

}

void TreeDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    sk::GameItem * item = reinterpret_cast<sk::GameItem *>(index.data().toLongLong());
    item->paint(painter, option, index.row(), index.column());
}

QSize TreeDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    sk::GameItem * item = reinterpret_cast<sk::GameItem *>(index.data().toLongLong());
    return item->sizeHint(option, index.row(), index.column());
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    _UD.mw = this;
    ui->setupUi(this);
    setWindowTitle(tr("Physics Game Editor"));

    _project = new sk::GameProject();
    _UD.project = _project;

    _projectExplorer = 0; _dwProjectExplorer = 0;
    _levelEditor = 0; //_dwLevelEditor = 0;

    _model = new sk::GameModel(this);

    removeToolBar(ui->mainToolBar);

    _loadGeometry();
    statusBar()->hide();
}

MainWindow::~MainWindow()
{    
    delete ui;
    delete _project;
}

sk::GameProject * MainWindow::project()
{
    return _project;
}

void MainWindow::closeProject(bool save)
{
    if (_project->isEmpty())
    {
        return;
    }
    _projectExplorer->setModel(0);
    _model->reload(0);
    _project->close(save);
    //removeDockWidget(_dwLevelEditor);
    removeDockWidget(_dwProjectExplorer);
    //delete _dwLevelEditor;
    delete _dwProjectExplorer;
    setCentralWidget(0);
    delete _levelEditor;
    _UD.le = _levelEditor = 0; //_dwLevelEditor = 0;
    _UD.pe = _projectExplorer = 0; _dwProjectExplorer = 0;
}

sk::GameModel * MainWindow::model()
{
    return _model;
}

void MainWindow::onLevelDoubleClicked(sk::LevelItem * item)
{
    _levelEditor->setLevelItem(item);
}


void MainWindow::_newProjectLoaded()
{
    setWindowTitle(tr("Physics Game Editor - ") + _project->name());
    _projectExplorer = new ProjectExplorer(this);
    _UD.pe = _projectExplorer;
    _projectExplorer->setItemDelegate(new TreeDelegate(this));
    _levelEditor = new LevelEditor(this);

    _dwProjectExplorer = new QDockWidget(tr("Project Explorer"), this);
    _dwProjectExplorer->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    _model->reload(new sk::RootItem(_project));
    _projectExplorer->setModel(_model);
    _dwProjectExplorer->setWidget(_projectExplorer);
    _dwProjectExplorer->setObjectName(tr("dwProjectExplorer"));
    addDockWidget(Qt::LeftDockWidgetArea, _dwProjectExplorer);

    setCentralWidget(_levelEditor);

    ui->menuView->clear();    
    ui->menuView->addAction(_dwProjectExplorer->toggleViewAction());

    _loadGeometry();
}

void MainWindow::_closeProjectCheckSave()
{
    if (!_project->isEmpty() && _project->isDirty())
    {
        int res = QMessageBox::question(this, tr("Project is opened"), tr("Do you want to save existing project?"), QMessageBox::Yes, QMessageBox::No);
        closeProject(res == QMessageBox::Yes);
    }
    else
    {
        closeProject(false);
    }
    setWindowTitle(tr("Physics Game Editor"));
    _saveGeometry();
}

void MainWindow::on_actionNew_triggered()
{
    _closeProjectCheckSave();
    QString path = QFileDialog::getSaveFileName(this, tr("Choose project location and name"), _UD.lastDirectory());
    if (path.isEmpty())
    {
        return;
    }
    _UD.setLastDirectory(path);
    if (!_project->create(path))
    {
        QMessageBox::critical(this, tr("Error"), tr("Can not create project"));
        return;
    }
    _newProjectLoaded();
}

void MainWindow::on_actionAbout_triggered()
{
    WidgetAbout* widAbout = new WidgetAbout(this);
    widAbout->show();
}

void MainWindow::on_actionNewLevel_triggered()
{
    if (!_projectExplorer)
    {
        return;
    }
    _projectExplorer->on_btnNew_clicked();
}

void MainWindow::closeEvent(QCloseEvent * event)
{
    _closeProjectCheckSave();
    QMainWindow::closeEvent(event);
}

void MainWindow::on_actionSave_triggered()
{
    if (!_project->saveToDisk())
    {
        QMessageBox::critical(this, tr("Error"), "Project was not saved.");
    }
    _saveGeometry();
}

void MainWindow::_saveGeometry()
{
    QSettings settings(SETTINGS_DEVELOPER, SETTINGS_SOFWARE);
    QByteArray ba = saveGeometry();
    settings.setValue("Geometry/MainWindow", ba);
    settings.setValue("State/MainWindow", saveState(GEOMETRY_VERSION));
}

void MainWindow::_loadGeometry()
{
    QSettings settings(SETTINGS_DEVELOPER, SETTINGS_SOFWARE);
    QByteArray ba = settings.value("Geometry/MainWindow").toByteArray();
    restoreState(settings.value("State/MainWindow").toByteArray(), GEOMETRY_VERSION);
    restoreGeometry(ba);
    //Q_ASSERT(isOk);
    //setWindowState(windowState() | Qt::WindowMaximized);
    //restoreDockWidget(_dwProjectExplorer);
}

void MainWindow::on_actionOpen_triggered()
{

    QString path = QFileDialog::getOpenFileName(this, tr("Choose project location and name"), _UD.lastDirectory(), tr("Game Project (*.gameproj)"));
    if (path.isEmpty())
    {
        return;
    }
    if (path == _project->path())
    {
        QMessageBox::warning(this, tr("Warning"), tr("This project is already opened."));
        return;
    }
    _closeProjectCheckSave();
    _UD.setLastDirectory(path);
    if (!_project->open(path))
    {
        QMessageBox::critical(this, tr("Error"), tr("Can not open project:\n") + _project->errorString);
        return;
    }
    _newProjectLoaded();
}

void MainWindow::on_actionClose_triggered()
{
     _closeProjectCheckSave();
}

void MainWindow::on_actionDuplicate_triggered()
{
    _projectExplorer->on_btnClone_clicked();
}

void MainWindow::on_actionDelete_triggered()
{
    _projectExplorer->on_btnDelete_clicked();
}
